#include "ActorBehavior.h"
#include <libultraship/bridge/consolevariablebridge.h>
#include "2s2h/CustomItem/CustomItem.h"
#include "assets/2s2h_assets.h"
#include "2s2h/ObjectExtension/ActorListIndex.h"
#include "2s2h/ShipUtils.h"

extern "C" {
#include "variables.h"
#include "src/overlays/actors/ovl_Obj_Snowball/z_obj_snowball.h"
#include "src/overlays/actors/ovl_Obj_Snowball2/z_obj_snowball2.h"

void func_80B02D58(ObjSnowball* snowballActor, PlayState* play);
}

// clang-format off
std::map<std::tuple<s16, s16, s16>, RandoCheckId> snowballActorIdMap = {
    { { SCENE_11GORONNOSATO,    0,  29 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_01 },
    { { SCENE_11GORONNOSATO,    0,  30 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_02 },
    { { SCENE_11GORONNOSATO,    0,  31 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_03 },
    { { SCENE_11GORONNOSATO,    0,  32 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_04 },
    { { SCENE_11GORONNOSATO,    0,  33 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_05 },
    { { SCENE_11GORONNOSATO,    0,  34 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_06 },
    { { SCENE_11GORONNOSATO,    0,  35 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_07 },
    { { SCENE_11GORONNOSATO,    0,  36 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_08 },
    { { SCENE_11GORONNOSATO,    0,  37 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_09 },
    { { SCENE_11GORONNOSATO,    0,  38 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_10 },
    { { SCENE_11GORONNOSATO,    0,  39 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_11 },
    { { SCENE_11GORONNOSATO,    0,  40 }, RC_GORON_VILLAGE_SMALL_SNOWBALL_12 },
    { { SCENE_11GORONNOSATO,    0,  50 }, RC_GORON_VILLAGE_LARGE_SNOWBALL_01 },
    { { SCENE_11GORONNOSATO,    0,  51 }, RC_GORON_VILLAGE_LARGE_SNOWBALL_02 },
    { { SCENE_11GORONNOSATO,    0,  52 }, RC_GORON_VILLAGE_LARGE_SNOWBALL_03 },
    { { SCENE_11GORONNOSATO,    0,  53 }, RC_GORON_VILLAGE_LARGE_SNOWBALL_04 },
    { { SCENE_11GORONNOSATO,    0,  54 }, RC_GORON_VILLAGE_LARGE_SNOWBALL_05 },
    { { SCENE_11GORONNOSATO,    0,  55 }, RC_GORON_VILLAGE_LARGE_SNOWBALL_06 },
    { { SCENE_11GORONNOSATO,    0,  56 }, RC_GORON_VILLAGE_LARGE_SNOWBALL_07 },
    { { SCENE_11GORONNOSATO,    0,  57 }, RC_GORON_VILLAGE_LARGE_SNOWBALL_08 },
    { { SCENE_11GORONNOSATO,    0,  58 }, RC_GORON_VILLAGE_LARGE_SNOWBALL_09 },
    { { SCENE_10YUKIYAMANOMURA, 0,  39 }, RC_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_01 },
    { { SCENE_10YUKIYAMANOMURA, 0,  40 }, RC_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_02 },
    { { SCENE_10YUKIYAMANOMURA, 0,  41 }, RC_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_03 },
    { { SCENE_10YUKIYAMANOMURA, 0,  42 }, RC_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_04 },
    { { SCENE_10YUKIYAMANOMURA, 0,  43 }, RC_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_05 },
    { { SCENE_10YUKIYAMANOMURA, 0,  49 }, RC_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_10 },
    { { SCENE_10YUKIYAMANOMURA, 0,  50 }, RC_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_11 },
    { { SCENE_10YUKIYAMANOMURA, 0,  53 }, RC_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_08 },
    { { SCENE_10YUKIYAMANOMURA, 0,  54 }, RC_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_09 },
    { { SCENE_10YUKIYAMANOMURA, 0,  55 }, RC_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_06 },
    { { SCENE_10YUKIYAMANOMURA, 0,  56 }, RC_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_07 },
    { { SCENE_13HUBUKINOMITI,   0,  33 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_08 },
    { { SCENE_13HUBUKINOMITI,   0,  34 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_05 },
    { { SCENE_13HUBUKINOMITI,   0,  35 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_06 },
    { { SCENE_13HUBUKINOMITI,   0,  36 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_07 },
    { { SCENE_13HUBUKINOMITI,   0,  37 }, RC_PATH_TO_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_01 },
    { { SCENE_13HUBUKINOMITI,   0,  38 }, RC_PATH_TO_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_02 },
    { { SCENE_13HUBUKINOMITI,   0,  39 }, RC_PATH_TO_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_03 },
    { { SCENE_13HUBUKINOMITI,   0,  40 }, RC_PATH_TO_MOUNTAIN_VILLAGE_SMALL_SNOWBALL_04 },
    { { SCENE_14YUKIDAMANOMITI, 0,  9 },  RC_PATH_TO_SNOWHEAD_SMALL_SNOWBALL_01 },
    { { SCENE_14YUKIDAMANOMITI, 0,  10 }, RC_PATH_TO_SNOWHEAD_SMALL_SNOWBALL_02 },
    { { SCENE_14YUKIDAMANOMITI, 0,  11 }, RC_PATH_TO_SNOWHEAD_SMALL_SNOWBALL_03 },
    { { SCENE_14YUKIDAMANOMITI, 0,  28 }, RC_PATH_TO_SNOWHEAD_LARGE_SNOWBALL_03 },
    { { SCENE_14YUKIDAMANOMITI, 0,  29 }, RC_PATH_TO_SNOWHEAD_LARGE_SNOWBALL_04 },
    { { SCENE_14YUKIDAMANOMITI, 0,  30 }, RC_PATH_TO_SNOWHEAD_LARGE_SNOWBALL_01 },
    { { SCENE_14YUKIDAMANOMITI, 0,  31 }, RC_PATH_TO_SNOWHEAD_LARGE_SNOWBALL_02 },
    { { SCENE_12HAKUGINMAE,     0,  42 }, RC_SNOWHEAD_SMALL_SNOWBALL_01 },
    { { SCENE_12HAKUGINMAE,     0,  43 }, RC_SNOWHEAD_SMALL_SNOWBALL_02 },
    { { SCENE_12HAKUGINMAE,     0,  44 }, RC_SNOWHEAD_SMALL_SNOWBALL_03 },
    { { SCENE_12HAKUGINMAE,     0,  45 }, RC_SNOWHEAD_SMALL_SNOWBALL_04 },
    { { SCENE_12HAKUGINMAE,     0,  46 }, RC_SNOWHEAD_LARGE_SNOWBALL_01 },
    { { SCENE_12HAKUGINMAE,     0,  47 }, RC_SNOWHEAD_LARGE_SNOWBALL_02 },
    { { SCENE_12HAKUGINMAE,     0,  48 }, RC_SNOWHEAD_LARGE_SNOWBALL_03 },
    { { SCENE_12HAKUGINMAE,     0,  49 }, RC_SNOWHEAD_LARGE_SNOWBALL_04 },
    { { SCENE_12HAKUGINMAE,     0,  50 }, RC_SNOWHEAD_LARGE_SNOWBALL_05 },
    { { SCENE_12HAKUGINMAE,     0,  51 }, RC_SNOWHEAD_LARGE_SNOWBALL_06 },
    { { SCENE_HAKUGIN,          2,  3 },  RC_SNOWHEAD_TEMPLE_BRIDGE_ROOM_SMALL_SNOWBALL_01 },
    { { SCENE_HAKUGIN,          2,  4 },  RC_SNOWHEAD_TEMPLE_BRIDGE_ROOM_SMALL_SNOWBALL_02 },
    { { SCENE_HAKUGIN,          4,  33 }, RC_SNOWHEAD_TEMPLE_CENTRAL_ROOM_LEVEL_2_SMALL_SNOWBALL_06 },
    { { SCENE_HAKUGIN,          4,  34 }, RC_SNOWHEAD_TEMPLE_CENTRAL_ROOM_LEVEL_2_SMALL_SNOWBALL_04 },
    { { SCENE_HAKUGIN,          4,  35 }, RC_SNOWHEAD_TEMPLE_CENTRAL_ROOM_LEVEL_2_SMALL_SNOWBALL_03 },
    { { SCENE_HAKUGIN,          4,  36 }, RC_SNOWHEAD_TEMPLE_CENTRAL_ROOM_LEVEL_2_SMALL_SNOWBALL_02 },
    { { SCENE_HAKUGIN,          4,  37 }, RC_SNOWHEAD_TEMPLE_CENTRAL_ROOM_LEVEL_2_SMALL_SNOWBALL_01 },
    { { SCENE_HAKUGIN,          4,  38 }, RC_SNOWHEAD_TEMPLE_CENTRAL_ROOM_LEVEL_2_SMALL_SNOWBALL_05 },
    { { SCENE_HAKUGIN,          4,  75 }, RC_SNOWHEAD_TEMPLE_CENTRAL_ROOM_LEVEL_3_LARGE_SNOWBALL_01 },
    { { SCENE_HAKUGIN,          4,  76 }, RC_SNOWHEAD_TEMPLE_CENTRAL_ROOM_LEVEL_3_LARGE_SNOWBALL_02 },
    { { SCENE_HAKUGIN,          4,  77 }, RC_SNOWHEAD_TEMPLE_CENTRAL_ROOM_LEVEL_3_LARGE_SNOWBALL_03 },
    { { SCENE_HAKUGIN,          4,  78 }, RC_SNOWHEAD_TEMPLE_CENTRAL_ROOM_LEVEL_3_LARGE_SNOWBALL_04 },
    { { SCENE_HAKUGIN,          7,  8 },  RC_SNOWHEAD_TEMPLE_ICICLE_ROOM_SMALL_SNOWBALL_01 },
    { { SCENE_HAKUGIN,          7,  9 },  RC_SNOWHEAD_TEMPLE_ICICLE_ROOM_SMALL_SNOWBALL_02 },
    { { SCENE_HAKUGIN,          7,  10 }, RC_SNOWHEAD_TEMPLE_ICICLE_ROOM_SMALL_SNOWBALL_03 },
    { { SCENE_HAKUGIN,          7,  11 }, RC_SNOWHEAD_TEMPLE_ICICLE_ROOM_SMALL_SNOWBALL_04 },
    { { SCENE_HAKUGIN,          7,  12 }, RC_SNOWHEAD_TEMPLE_ICICLE_ROOM_SMALL_SNOWBALL_05 },
    { { SCENE_HAKUGIN,          7,  26 }, RC_SNOWHEAD_TEMPLE_ICICLE_ROOM_LARGE_SNOWBALL_01 },
    { { SCENE_HAKUGIN,          10, 8 },  RC_SNOWHEAD_TEMPLE_SNOW_ROOM_SMALL_SNOWBALL_01 },
    { { SCENE_HAKUGIN,          10, 9 },  RC_SNOWHEAD_TEMPLE_SNOW_ROOM_SMALL_SNOWBALL_02 },
    { { SCENE_HAKUGIN,          10, 10 }, RC_SNOWHEAD_TEMPLE_SNOW_ROOM_SMALL_SNOWBALL_03 },
    { { SCENE_HAKUGIN,          10, 11 }, RC_SNOWHEAD_TEMPLE_SNOW_ROOM_SMALL_SNOWBALL_04 },
    { { SCENE_HAKUGIN,          10, 12 }, RC_SNOWHEAD_TEMPLE_SNOW_ROOM_SMALL_SNOWBALL_05 },
    { { SCENE_HAKUGIN,          10, 13 }, RC_SNOWHEAD_TEMPLE_SNOW_ROOM_SMALL_SNOWBALL_06 },
    { { SCENE_HAKUGIN,          10, 14 }, RC_SNOWHEAD_TEMPLE_SNOW_ROOM_SMALL_SNOWBALL_07 },
    { { SCENE_HAKUGIN,          10, 15 }, RC_SNOWHEAD_TEMPLE_SNOW_ROOM_SMALL_SNOWBALL_08 },
    { { SCENE_17SETUGEN,        0,  62 }, RC_TWIN_ISLANDS_SMALL_SNOWBALL_01 },
    { { SCENE_17SETUGEN,        0,  63 }, RC_TWIN_ISLANDS_SMALL_SNOWBALL_02 },
    { { SCENE_17SETUGEN,        0,  64 }, RC_TWIN_ISLANDS_SMALL_SNOWBALL_03 },
    { { SCENE_17SETUGEN,        0,  65 }, RC_TWIN_ISLANDS_SMALL_SNOWBALL_04 },
    { { SCENE_17SETUGEN,        0,  66 }, RC_TWIN_ISLANDS_SMALL_SNOWBALL_05 },
    { { SCENE_17SETUGEN,        0,  67 }, RC_TWIN_ISLANDS_SMALL_SNOWBALL_06 },

    // The following large snowballs have different ActorListIndex values each day. Having repeat check map entries is
    // fine, so long as there are no overlaps in values for a given scene. Duplicates are organized by Day 1, 2, 3:
    { { SCENE_10YUKIYAMANOMURA, 0, 14 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_01 },
    { { SCENE_10YUKIYAMANOMURA, 0, 45 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_01 },
    { { SCENE_10YUKIYAMANOMURA, 0, 16 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_01 },
    { { SCENE_10YUKIYAMANOMURA, 0, 17 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_02 },
    { { SCENE_10YUKIYAMANOMURA, 0, 13 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_02 },
    { { SCENE_10YUKIYAMANOMURA, 0, 12 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_02 },
    { { SCENE_10YUKIYAMANOMURA, 0, 18 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_03 },
    { { SCENE_10YUKIYAMANOMURA, 0, 47 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_03 },
    { { SCENE_10YUKIYAMANOMURA, 0, 44 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_03 },
    { { SCENE_10YUKIYAMANOMURA, 0, 46 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_04 },
    { { SCENE_10YUKIYAMANOMURA, 0, 48 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_04 },
    { { SCENE_10YUKIYAMANOMURA, 0, 34 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_04 },
    { { SCENE_10YUKIYAMANOMURA, 0, 52 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_05 },
    { { SCENE_10YUKIYAMANOMURA, 0, 15 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_05 },
    { { SCENE_10YUKIYAMANOMURA, 0, 51 }, RC_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_05 },
    { { SCENE_13HUBUKINOMITI,   0, 26 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_01 },
    { { SCENE_13HUBUKINOMITI,   0, 28 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_01 },
    { { SCENE_13HUBUKINOMITI,   0, 23 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_01 },
    { { SCENE_13HUBUKINOMITI,   0, 42 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_02 },
    { { SCENE_13HUBUKINOMITI,   0, 24 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_02 },
    { { SCENE_13HUBUKINOMITI,   0, 19 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_02 },
    { { SCENE_13HUBUKINOMITI,   0, 31 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_03 },
    { { SCENE_13HUBUKINOMITI,   0, 46 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_03 },
    { { SCENE_13HUBUKINOMITI,   0, 22 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_03 },
    { { SCENE_13HUBUKINOMITI,   0, 30 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_04 },
    { { SCENE_13HUBUKINOMITI,   0, 27 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_04 },
    { { SCENE_13HUBUKINOMITI,   0, 29 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_04 },
    { { SCENE_13HUBUKINOMITI,   0, 41 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_09 },
    { { SCENE_13HUBUKINOMITI,   0, 45 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_09 },
    { { SCENE_13HUBUKINOMITI,   0, 47 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_09 },
    { { SCENE_13HUBUKINOMITI,   0, 43 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_10 },
    { { SCENE_13HUBUKINOMITI,   0, 48 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_10 },
    { { SCENE_13HUBUKINOMITI,   0, 20 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_10 },
    { { SCENE_13HUBUKINOMITI,   0, 44 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_11 },
    { { SCENE_13HUBUKINOMITI,   0, 25 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_11 },
    { { SCENE_13HUBUKINOMITI,   0, 21 }, RC_PATH_TO_MOUNTAIN_VILLAGE_LARGE_SNOWBALL_11 },
    { { SCENE_17SETUGEN,        0, 18 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_01 },
    { { SCENE_17SETUGEN,        0, 53 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_01 },
    { { SCENE_17SETUGEN,        0, 43 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_01 },
    { { SCENE_17SETUGEN,        0, 19 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_02 },
    { { SCENE_17SETUGEN,        0, 49 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_02 },
    { { SCENE_17SETUGEN,        0, 45 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_02 },
    { { SCENE_17SETUGEN,        0, 22 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_03 },
    { { SCENE_17SETUGEN,        0, 17 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_03 },
    { { SCENE_17SETUGEN,        0, 42 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_03 },
    { { SCENE_17SETUGEN,        0, 30 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_04 },
    { { SCENE_17SETUGEN,        0, 52 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_04 },
    { { SCENE_17SETUGEN,        0, 44 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_04 },
    { { SCENE_17SETUGEN,        0, 54 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_05 },
    { { SCENE_17SETUGEN,        0, 21 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_05 },
    { { SCENE_17SETUGEN,        0, 28 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_05 },
    { { SCENE_17SETUGEN,        0, 55 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_06 },
    { { SCENE_17SETUGEN,        0, 51 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_06 },
    { { SCENE_17SETUGEN,        0, 13 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_06 },
    { { SCENE_17SETUGEN,        0, 56 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_07 },
    { { SCENE_17SETUGEN,        0, 47 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_07 },
    { { SCENE_17SETUGEN,        0, 40 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_07 },
    { { SCENE_17SETUGEN,        0, 57 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_08 },
    { { SCENE_17SETUGEN,        0, 48 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_08 },
    { { SCENE_17SETUGEN,        0, 20 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_08 },
    { { SCENE_17SETUGEN,        0, 58 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_09 },
    { { SCENE_17SETUGEN,        0, 16 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_09 },
    { { SCENE_17SETUGEN,        0, 46 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_09 },
    { { SCENE_17SETUGEN,        0, 59 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_10 },
    { { SCENE_17SETUGEN,        0, 11 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_10 },
    { { SCENE_17SETUGEN,        0, 14 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_10 },
    { { SCENE_17SETUGEN,        0, 60 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_11 },
    { { SCENE_17SETUGEN,        0, 29 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_11 },
    { { SCENE_17SETUGEN,        0, 41 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_11 },
    { { SCENE_17SETUGEN,        0, 61 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_12 },
    // Note: RC_TWIN_ISLANDS_LARGE_SNOWBALL_12 does not exist on Day 2
    { { SCENE_17SETUGEN,        0, 15 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_12 },
    { { SCENE_17SETUGEN,        0, 12 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_13 },
    { { SCENE_17SETUGEN,        0, 50 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_13 },
    { { SCENE_17SETUGEN,        0,  4 }, RC_TWIN_ISLANDS_LARGE_SNOWBALL_13 },
};
// clang-format on

// Identify the snowball based on scene ID, room, and actor list index
void IdentifySnowball(Actor* actor, bool* should) {
    s16 actorListIndex = GetActorListIndex(actor);
    RandoCheckId randoCheckId = RC_UNKNOWN;

    auto it = snowballActorIdMap.find({ gPlayState->sceneId, gPlayState->roomCtx.curRoom.num, actorListIndex });
    if (it != snowballActorIdMap.end()) {
        randoCheckId = it->second;
    }

    if (!RANDO_SAVE_CHECKS[randoCheckId].shuffled || RANDO_SAVE_CHECKS[randoCheckId].cycleObtained) {
        return;
    }

    Rando::ActorBehavior::SetObjectRandoCheckId(actor, randoCheckId);
}

void SpawnSnowballDrop(Vec3f pos, RandoCheckId randoCheckId) {
    CustomItem::Spawn(
        pos.x, pos.y, pos.z, 0, CustomItem::KILL_ON_TOUCH | CustomItem::TOSS_ON_SPAWN | CustomItem::ABLE_TO_ZORA_RANG,
        randoCheckId,
        [](Actor* actor, PlayState* play) {
            RandoSaveCheck& randoSaveCheck = RANDO_SAVE_CHECKS[CUSTOM_ITEM_PARAM];
            randoSaveCheck.eligible = true;
        },
        [](Actor* actor, PlayState* play) {
            auto& randoSaveCheck = RANDO_SAVE_CHECKS[CUSTOM_ITEM_PARAM];
            Matrix_Scale(30.0f, 30.0f, 30.0f, MTXMODE_APPLY);
            Rando::DrawItem(Rando::ConvertItem(randoSaveCheck.randoItemId, (RandoCheckId)CUSTOM_ITEM_PARAM), actor);
        });
}

void Rando::ActorBehavior::InitObjSnowballBehavior() {
    COND_ID_HOOK(ShouldActorInit, ACTOR_OBJ_SNOWBALL, IS_RANDO, IdentifySnowball);
    COND_ID_HOOK(ShouldActorInit, ACTOR_OBJ_SNOWBALL2, IS_RANDO, IdentifySnowball);

    COND_VB_SHOULD(VB_SNOWBALL_DROP_COLLECTIBLE, IS_RANDO, {
        Actor* actor = va_arg(args, Actor*);

        RandoCheckId randoCheckId = GetObjectRandoCheckId(actor);

        if (randoCheckId == RC_UNKNOWN) {
            return;
        }

        if (!RANDO_SAVE_CHECKS[randoCheckId].cycleObtained) {
            SpawnSnowballDrop(actor->world.pos, randoCheckId);
            *should = false;
        }
    });

    COND_VB_SHOULD(VB_SNOWBALL_SET_FLAG, IS_RANDO, {
        Actor* actor = va_arg(args, Actor*);
        ActorId actorToSpawn = (ActorId)va_arg(args, s32);
        ObjSnowballActionFunc actorFunction = va_arg(args, ObjSnowballActionFunc);

        // Ignore snowballs that drop a collectable, those are handled above with VB_SNOWBALL_DROP_COLLECTIBLE
        if (actorFunction == func_80B02D58) {
            return;
        }

        RandoCheckId randoCheckId = GetObjectRandoCheckId(actor);

        if (randoCheckId == RC_UNKNOWN) {
            return;
        }

        if (!RANDO_SAVE_CHECKS[randoCheckId].cycleObtained) {
            SpawnSnowballDrop(actor->world.pos, randoCheckId);
        }
    });
}
